Home:ALL Converter>How to slow down UIDocument's initial loadFromContents:ofType:error:?

How to slow down UIDocument's initial loadFromContents:ofType:error:?

Ask Time:2012-06-22T04:13:36         Author:tobinjim

Json Formatter

When I drag a file package from Finder into the iTunes.app file sharing pane, my UIDocument class is trying to read in the associated file wrappers, and it appears my code to read it is executing faster than iTunes.app can copy the contents over. The initial file wrappers array contains only one of the two files inside the wrapper.

So how do I "slow" my code down?

I ran a test using performSelector:withObject:AfterDelay:1.0f, and that worked fine, but that feels really risky: What if a really large file is dragged in to iTunes (by really large I mean one that exceeds my delay)? What if multiple files are all dropped on at the same time?

I looked at somehow discerning that the file is ready to be read, but Apple's NSFileManager documentation says

"It's far better to attempt an operation (such as loading a file or creating a directory), check for errors, and handle those errors gracefully than it is to try to figure out ahead of time whether the operation will succeed."

But where the timing problem comes up is during the decoding of the constituent file wrappers, so how to handle it "gracefully" is eluding me.

My package file has two data files within it (at this early stage, but the design is because there will be more): data.dat and info.dat. When I first got code working to the point where I could drag a file into iTunes.app and notice it in my view controller, data.dat was always decoding fine, but info.dat was not found. Once the file is inside my local documents folder, the view controller presents all the data as expected (i.e. info.dat is inside the file wrapper and correctly formed). Suspecting this to be a timing issue, I renamed the filename constants and on-disk files to zdata.dat and ainfo.dat -- sure enough: ainfo.dat loads and my UIDocument subclass complains that zdata.dat wasn't found.

I use lazy loading, but the view controller has an immediate interest in the info.dat contents, so lazy loading isn't lazy enough for iTunes to get through copying!

From my UIDocument subclass implementation:

- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError
{
    self.fileWrapper = (NSFileWrapper *)contents;

    // Lazy load everything!

    _data = nil;
    _metadata = nil;

    return YES;
}

- (id)decodeObjectFromWrapperWithPreferredFilename:(NSString *)preferredFilename
{
    NSFileWrapper *fw = [self.fileWrapper.fileWrappers objectForKey:preferredFilename];
    if (!fw) {
        NSLog(@"Unexpected error: Couldn't find %@ in the file wrapper for %@", preferredFilename, self.fileURL);
        return nil;
    }
    NSData *data = [fw regularFileContents];
    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];

    return [unarchiver decodeObjectForKey:@"data"];
}

- (GSBMetadata *)metadata
{
    if (_metadata == nil) {
        if (self.fileWrapper != nil) {
           // NSLog(@"Loading metadata for %@...",self.fileURL);
            _metadata = [self decodeObjectFromWrapperWithPreferredFilename:kGSBMetadataFileName];
        } else {
            _metadata = [[GSBMetadata alloc] init];
        }
    }
    return _metadata;
}

The problem is discovered in decodeObjectFromWrapperWithPreferredFilename: when the check is made to ensure that the expected file wrapper is present. Normally this would be the case if the file was corrupt, or perhaps version 2 of the app used a different file format. But gracefully handling those circumstances fall under the heading of "paranoid programming expected that sort of thing" and not under the heading of "just wait a second and all your data will be available to you."

Author:tobinjim,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/11146019/how-to-slow-down-uidocuments-initial-loadfromcontentsoftypeerror
yy